package com.linkallcloud.core.www;

import java.io.Serializable;
import java.time.Duration;
import java.time.LocalDateTime;

import com.linkallcloud.core.exception.BizException;
import com.linkallcloud.core.lang.Strings;
import com.linkallcloud.core.util.Date8;

/**
 * 
 * @author hzzdong
 *
 */
public class LacToken implements Serializable {
    private static final long serialVersionUID = 276925919164426285L;

    private String loginName;
    private int clazz;// user class
    private String appCode;// 票据方法应用编码
    private String tokenKey;// token 随机数
    private String ttime;// token创建时间(yyyyMMddHHmmss)
    private int ttl;// 有效时长，unit:Minute

    /**
     * 
     * @param token
     *            loginName|clazz|appCode|tokenKey|ttime
     */
    public LacToken(String token) {
        super();
        if (Strings.isBlank(token)) {
            throw new BizException("100002", "token验证失败：token为空。");
        }

        String[] fields = token.split("\\|");
        if (fields == null || fields.length != 5) {
            throw new BizException("100002", "token验证失败。");
        }

        this.loginName = fields[0];
        this.clazz = Integer.parseInt(fields[1]);
        this.appCode = fields[2];
        this.tokenKey = fields[3];
        this.ttime = fields[4];
    }

    public LacToken(ISimpleUser user, String tokenKey, Duration timeout) {
        this.loginName = user.getLoginName();
        this.clazz = user.getUserClazz();
        this.appCode = user.appCode();
        this.tokenKey = tokenKey;

        this.ttl = (timeout != null) ? (int) timeout.toMinutes() : 10;

        LocalDateTime now = LocalDateTime.now();
        // LocalDateTime end = Date8.addTime(now, ChronoUnit.MINUTES, minutes);
        // this.ttime = Date8.formatLocalDateTimeToString(end, "yyyyMMddHHmmss");
        this.ttime = Date8.formatLocalDateTimeToString(now, "yyyyMMddHHmmss");
    }

    /**
     * loginName|clazz|appCode|tokenKey|ttime
     */
    public String toToken() {
        StringBuffer sb = new StringBuffer();
        sb.append(this.loginName).append("|").append(this.clazz).append("|").append(this.appCode).append("|")
                .append(this.tokenKey).append("|").append(this.ttime);
        return sb.toString();
    }

    public String getLoginName() {
        return loginName;
    }

    public int getClazz() {
        return clazz;
    }

    public String getAppCode() {
        return appCode;
    }

    public String getTtime() {
        return ttime;
    }

    public void setTtime(String ttime) {
        this.ttime = ttime;
    }

    public int getTtl() {
        return ttl;
    }

    public void setTtl(int ttl) {
        this.ttl = ttl;
    }

    public boolean isTimeout() {
        // LocalDateTime begin = Date8.stringToLocalDateTime(this.getTtime(), "yyyyMMddHHmmss");
        // 暂时不校验token最长有效时间（比如ttl为10分钟，一直有请求的情况下，token最长有效期是否需要限制？），后续再考虑
        return true;
    }

    public LacToken check() {
        if (Strings.isBlank(this.loginName)) {
            throw new BizException("100002", "token验证失败：数据格式错误。");
        }
        // if (Strings.isBlank(this.clazz)) {
        // throw new BizException("100002", "token验证失败：数据格式错误。");
        // }
        if (Strings.isBlank(this.appCode)) {
            throw new BizException("100002", "appCode验证失败：数据格式错误。");
        }
        if (Strings.isBlank(this.tokenKey)) {
            throw new BizException("100002", "token验证失败：数据格式错误。");
        }
        if (Strings.isBlank(this.ttime)) {
            throw new BizException("100002", "token验证失败：数据格式错误。");
        }
        if (isTimeout()) {
            throw new BizException("100002", "token验证失败：超时错误。");
        }
        return this;
    }

    public <U extends ISimpleUser> U toSessionUser(ITokenBox box, Class<U> uclass) {
        check();

        U user = box.get(tokenKey, uclass);
        if (user == null) {
            throw new BizException("100002", "token验证失败：token数据错误。");
        }

        if (!user.getLoginName().equals(loginName)) {
            throw new BizException("100002", "token验证失败:loginName不匹配。");
        }

        return user;
    }

    public static void main(String args[]) {
        LocalDateTime now = LocalDateTime.now();
        String vtime = Date8.formatLocalDateTimeToString(now, "yyyyMMddHHmmss");
        System.out.println("vtime:" + vtime);

        LocalDateTime now2 = Date8.stringToLocalDateTime(vtime, "yyyyMMddHHmmss");
        String vtime2 = Date8.formatLocalDateTimeToString(now2, "yyyyMMddHHmmss");
        System.out.println("vtime2:" + vtime2);

    }

}
